#ifndef __GAME_WORLD_H__
#define __GAME_WORLD_H__

#include <memory>
#include <SFML/Graphics.hpp>
#include "Vector2D.h"

using namespace std;

enum GameViews
{
	VIEW_ONE,
	VIEW_TWO,
	VIEW_THREE,
	VIEW_FOUR,
	MAX_VIEWS
};

class BaseEntity;

class GameWorld
{
public:
	GameWorld( sf::RenderWindow* win );										// Constructor.
	~GameWorld();															// Destructor.

	void addEntity( BaseEntity *entity );									// Adds an Entity to the world.
	void removeEntity( BaseEntity *entity );								// Removes an Entity from the world.

	void draw( BaseEntity *entity );										// Draws a given Entity in the world.
	void draw( const sf::Drawable &drawable );								// Draws a given drawable in the world.

	void setNumberViews( int number );										// Sets the number of views, constrained between 1 and 4.
	void splitHorizontally( bool flag );									// Switches from vertical to horizontal split (two views only).

	void update(float dt = 0.0f);											// Updates each of the view positions and all entities in the world.
	void setWorldSize( int width, int height );								// Sets the size of the world.
	void setViewPosition( Vector2D position, int view = 0 );				// Sets the view position for a given view.

	void moveViewUp( unsigned int amount, int view = 0 );					// Moves the given view up by an amount.
	void moveViewDown( unsigned int amount, int view = 0 );					// Moves the given view down by an amount.
	void moveViewLeft( unsigned int amount, int view = 0 );					// Moves the given view left by an amount.
	void moveViewRight( unsigned int amount, int view = 0 );				// Moves the given view right by an amount.

	void enableFollowEntity( bool flag, int view = 0 );						// Enables/disables following a central entity (if set) in a given view.
	void setCentralEntity( BaseEntity *entity, int view = 0 );				// Sets an entity to keep central to the given view.

	int getWorldWidth() const;												// Returns the width of the world.
	int getWorldHeight() const;												// Returns the height of the world.
	int getCurrentView() const;												// Returns the current view being draw by the GameWorld.
	
	bool isInView( Vector2D position, float radius = 0.0f, int view = 0 );	// Returns true if the a point within "radius" around "position" is in the given view.
	bool isOnScreen( Vector2D position, float radius = 0.0f );				// Returns true if a point within "radius" around "position" is on screen (any view).

	sf::RenderWindow* getWindow() const;									// Returns a pointer to the window.
	vector<BaseEntity*> getEntities() const;								// Returns the entities vector.
private:
	sf::RenderWindow *win;													// The window which shows the game world.
	sf::View views[MAX_VIEWS];												// The views which the window can see.
	vector<BaseEntity*> entities;											// The entities within the game world.

	bool followEntities[MAX_VIEWS];											// True if following an entity, false by default.
	BaseEntity* centralEntities[MAX_VIEWS];									// An entity to follow in the centre of the window.
																			
	int worldWidth;															// The width of the world.
	int worldHeight;														// The height of the world.

	bool splitHorizontal;													// True if the two-view screen should be split horizontally, default is false.
	Vector2D viewPositions[MAX_VIEWS];										// The centre position of each view looking at the game world.
	int activeViews;														// The number of currently active views.
	int currentView;														// The current view being drawn at any time.
};

#endif // __GAME_WORLD_H__